#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
#define LINE_SIZE 1024
#define DELIM " "
#define EXIT_CODE 40


char command_line[LINE_SIZE];
//当前路径
char pwd[LINE_SIZE];

// 命令行参数表
char* argv[LINE_SIZE];
int argc = 0;

int last_code = 0;

char myenv[LINE_SIZE];
//int cnt = 0;

//extern char** environ;

char* get_user()
{
    return getenv("USER");
}

char* get_hostname()
{
    return getenv("HOSTNAME");
}

void get_pwd()
{
    getcwd(pwd, sizeof(pwd));
}

void interact(char* cline, int size)
{
    get_pwd();
    printf(LEFT"%s@%s %s"RIGHT""LABLE" ", get_user(), get_hostname(), pwd);
    char* s = fgets(cline, size, stdin);
    //printf("%s", s);
    assert(s);

    cline[strlen(cline) - 1] = '\0';
}

int split_string(char* _argv[], char* cline)
{
    int i = 0;
    _argv[i++] = strtok(cline, DELIM);
    while(_argv[i++] = strtok(NULL, DELIM));
    
    //printf("SSSSSSSSSSSSSSSSSSSS");
    /*
    for(int j = 1; _argv[j]; j++)
    {
        printf("%s ", _argv[j]);
    }
    */
    return i - 1;
}

void normal_excute(char* _argv[])
{
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        return;
    }
    else if (id == 0)
    {
        // child
        // 让子进程执行命令
        execvp(_argv[0], _argv);
        exit(EXIT_CODE);
    }
    else 
    {
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if(rid == id)
        {
            last_code = WEXITSTATUS(status);
        }
    }
}

int build_command(char* _argv[], int _argc)
{
    if(_argc == 2 && strcmp(_argv[0], "cd") == 0)
    {
        // 把当前目录修改为指定目录
        chdir(_argv[1]); 
        get_pwd();
        sprintf(getenv("PWD"), "%s", pwd);

        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0], "export") == 0)
    {
        strcmp(myenv, _argv[1]);
        putenv(myenv);

        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0], "echo") == 0) 
    {
        if(strcmp(argv[1], "$?") == 0)
        {
            // 显示上次个进程的退出码
            printf("%d\n", last_code);
            last_code = 0;
        }
        else if(*_argv[1] == '$')
        {
            char* val = getenv(_argv[1] + 1);
            if(val)
                printf("%s\n", val);
        }
        else 
        {
            printf("%s\n", _argv[1]);
        }

        return 1;
    }

    if(strcmp(_argv[0], "ls") == 0)
    {
        _argv[_argc++] = "--color";
        _argv[_argc] = NULL;
    }

    return 0;
}

int main()
{
    while(1)
    {
        //交互，获取命令行
        interact(command_line, sizeof(command_line));

        // 字串分割， 获得命令行参数表
        int argc = split_string(argv, command_line);

        // 判断是否为内建命令
        int n = build_command(argv, argc);
        
        // 普遍命令
        // 创建子进程 通过 进程替换 完成用户的指令
        if(!n)
            normal_excute(argv);
    }
    return 0;
}
